package com.personalink.reasoning.processor;

import com.personalink.common.dto.ChatRequest;
import com.personalink.common.dto.ChatResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 美食达人处理器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CulinaryProcessor implements PersonaProcessor {
    
    private final ChatClient chatClient;
    
    private static final String PERSONA_ID = "culinary-expert";
    private static final String PERSONA_NAME = "美食达人";
    
    private static final String SYSTEM_PROMPT = 
            "你是一位资深的美食达人和烹饪专家，拥有丰富的中西方料理经验。" +
            "你的专长包括：\n" +
            "1. 创意食谱设计和改良\n" +
            "2. 烹饪技巧指导和问题解决\n" +
            "3. 食材搭配和营养建议\n" +
            "4. 各地美食文化和历史\n" +
            "5. 餐厅推荐和美食评价\n\n" +
            "你的特点：\n" +
            "- 热情洋溢，对美食充满激情\n" +
            "- 善于用生动的语言描述味觉体验\n" +
            "- 注重食材的新鲜度和季节性\n" +
            "- 关注健康饮食和营养搭配\n" +
            "- 乐于分享烹饪心得和小窍门\n\n" +
            "回答风格：\n" +
            "- 使用丰富的美食词汇和感官描述\n" +
            "- 提供详细的步骤说明和注意事项\n" +
            "- 适当加入个人经验和故事\n" +
            "- 鼓励用户尝试和创新";
    
    private static final List<String> SUPPORTED_INPUT_TYPES = Arrays.asList(
            "text", "image", "mixed"
    );
    
    @Override
    public Mono<ChatResponse> processRequest(ChatRequest request) {
        long startTime = System.currentTimeMillis();
        
        return preprocessRequest(request)
                .flatMap(this::generateCulinaryResponse)
                .flatMap(this::postprocessResponse)
                .doOnNext(response -> {
                    response.setProcessingTime(System.currentTimeMillis() - startTime);
                    log.info("美食达人处理完成，响应ID: {}, 处理时间: {}ms", 
                            response.getResponseId(), response.getProcessingTime());
                });
    }
    
    @Override
    public Flux<ChatResponse> processRequestStream(ChatRequest request) {
        return preprocessRequest(request)
                .flatMapMany(this::generateCulinaryResponseStream)
                .map(this::createStreamResponse)
                .doOnNext(response -> log.debug("美食达人流式响应: {}", response.getResponseId()));
    }
    
    @Override
    public String getPersonaId() {
        return PERSONA_ID;
    }
    
    @Override
    public String getPersonaName() {
        return PERSONA_NAME;
    }
    
    @Override
    public boolean supportsInputType(String inputType) {
        return SUPPORTED_INPUT_TYPES.contains(inputType);
    }
    
    @Override
    public Mono<ChatRequest> preprocessRequest(ChatRequest request) {
        String content = request.getContent();
        
        // 检测食谱请求
        if (isRecipeRequest(content)) {
            request.getMetadata().put("requestType", "recipe");
            log.debug("检测到食谱请求，用户ID: {}", request.getUserId());
        }
        
        // 检测食材识别请求
        if (request.getInputType().equals("image")) {
            request.getMetadata().put("requestType", "ingredient_recognition");
            String enhancedContent = "请帮我识别这张图片中的食材，并推荐相应的烹饪方法：" + content;
            request.setContent(enhancedContent);
        }
        
        // 添加季节性建议提示
        if (content.contains("推荐") || content.contains("建议")) {
            String season = getCurrentSeason();
            String enhancedContent = content + "\n\n[当前是" + season + "，请考虑时令食材]";
            request.setContent(enhancedContent);
        }
        
        return Mono.just(request);
    }
    
    @Override
    public Mono<ChatResponse> postprocessResponse(ChatResponse response) {
        String content = response.getContent();
        
        // 添加美食小贴士
        if (response.getMetadata().containsKey("requestType") && 
            "recipe".equals(response.getMetadata().get("requestType"))) {
            content += "\n\n🍳 小贴士：烹饪时保持愉悦的心情，美食的味道会更加美妙哦！";
            response.setContent(content);
        }
        
        // 添加营养提醒
        if (content.contains("食谱") || content.contains("菜谱")) {
            content += "\n\n💡 温馨提醒：注意营养搭配，适量食用，享受健康美味！";
            response.setContent(content);
        }
        
        // 设置美食相关的元数据
        response.getMetadata().put("culinaryAdvice", true);
        response.getMetadata().put("season", getCurrentSeason());
        
        return Mono.just(response);
    }
    
    /**
     * 生成美食响应
     */
    private Mono<ChatResponse> generateCulinaryResponse(ChatRequest request) {
        List<Message> messages = Arrays.asList(
                new SystemMessage(SYSTEM_PROMPT),
                new UserMessage(request.getContent())
        );
        
        Prompt prompt = new Prompt(messages);
        
        return Mono.fromCallable(() -> chatClient.call(prompt))
                .map(result -> {
                    ChatResponse response = createBaseResponse(request);
                    response.setContent(result.getResult().getOutput().getContent());
                    response.setResponseType("culinary_advice");
                    
                    // 添加美食相关元数据
                    response.getMetadata().put("cuisine", detectCuisineType(request.getContent()));
                    response.getMetadata().put("difficulty", estimateDifficulty(result));
                    response.getMetadata().put("cookingTime", estimateCookingTime(result));
                    
                    return response;
                })
                .onErrorResume(error -> {
                    log.error("美食响应生成失败", error);
                    return Mono.just(createErrorResponse(request, "美食咨询服务暂时不可用，请稍后重试"));
                });
    }
    
    /**
     * 生成流式美食响应
     */
    private Flux<String> generateCulinaryResponseStream(ChatRequest request) {
        List<Message> messages = Arrays.asList(
                new SystemMessage(SYSTEM_PROMPT),
                new UserMessage(request.getContent())
        );
        
        Prompt prompt = new Prompt(messages);
        
        return Flux.fromStream(() -> chatClient.stream(prompt)
                .map(result -> result.getResult().getOutput().getContent()))
                .onErrorResume(error -> {
                    log.error("美食流式响应生成失败", error);
                    return Flux.just("美食咨询服务暂时不可用，请稍后重试。");
                });
    }
    
    /**
     * 创建基础响应对象
     */
    private ChatResponse createBaseResponse(ChatRequest request) {
        ChatResponse response = new ChatResponse();
        response.setResponseId(UUID.randomUUID().toString());
        response.setUserId(request.getUserId());
        response.setSessionId(request.getSessionId());
        response.setPersonaId(PERSONA_ID);
        response.setTimestamp(LocalDateTime.now());
        return response;
    }
    
    /**
     * 创建流式响应对象
     */
    private ChatResponse createStreamResponse(String content) {
        ChatResponse response = new ChatResponse();
        response.setResponseId(UUID.randomUUID().toString());
        response.setPersonaId(PERSONA_ID);
        response.setContent(content);
        response.setResponseType("culinary_advice_stream");
        response.setTimestamp(LocalDateTime.now());
        return response;
    }
    
    /**
     * 创建错误响应
     */
    private ChatResponse createErrorResponse(ChatRequest request, String errorMessage) {
        ChatResponse response = createBaseResponse(request);
        response.setContent(errorMessage);
        response.setResponseType("error");
        return response;
    }
    
    /**
     * 检测是否为食谱请求
     */
    private boolean isRecipeRequest(String content) {
        String[] recipeKeywords = {
                "食谱", "菜谱", "做法", "怎么做", "制作方法", 
                "烹饪", "料理", "配方", "步骤"
        };
        
        String lowerContent = content.toLowerCase();
        return Arrays.stream(recipeKeywords)
                .anyMatch(keyword -> lowerContent.contains(keyword.toLowerCase()));
    }
    
    /**
     * 获取当前季节
     */
    private String getCurrentSeason() {
        int month = LocalDateTime.now().getMonthValue();
        if (month >= 3 && month <= 5) {
            return "春季";
        } else if (month >= 6 && month <= 8) {
            return "夏季";
        } else if (month >= 9 && month <= 11) {
            return "秋季";
        } else {
            return "冬季";
        }
    }
    
    /**
     * 检测菜系类型
     */
    private String detectCuisineType(String content) {
        if (content.contains("川菜") || content.contains("麻辣")) {
            return "sichuan";
        } else if (content.contains("粤菜") || content.contains("广东")) {
            return "cantonese";
        } else if (content.contains("西餐") || content.contains("意大利")) {
            return "western";
        } else if (content.contains("日料") || content.contains("寿司")) {
            return "japanese";
        } else {
            return "general";
        }
    }
    
    /**
     * 估算难度等级
     */
    private String estimateDifficulty(Object result) {
        // 简单的难度估算逻辑
        return "medium"; // 默认中等难度
    }
    
    /**
     * 估算烹饪时间
     */
    private String estimateCookingTime(Object result) {
        // 简单的时间估算逻辑
        return "30-45分钟"; // 默认时间
    }
}